package com.nts.visionworks.business.streamevent.service;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.nts.visionworks.business.streamevent.domain.StreamEvent;
import com.nts.visionworks.business.streamevent.domain.StreamSynapse;
import com.nts.visionworks.business.streamevent.domain.StreamSynapseCoefficient;
import com.nts.visionworks.business.streamevent.domain.StreamSynapseTransmitter;

/**
 * 스트림 이벤트에 대한 DAO를 제공한다.
 * @author Devcken
 */
@Service("streamEventService")
@Transactional
public class StreamEventService
{
	/**
	 * VisionWorks {@link org.hibernate.SessionFactory}를 주입받는다.
	 */
	@Resource(name="visionworksSessionFactory")
	private SessionFactory _sessionFactory;
	
	/**
	 * 스트림 이벤트 목록을 조회한다.
	 * @param streamEventName 검색하려는 스트림 이벤트의 이름을 설정한다.
	 * @return 조회된 스트림 이벤트 목록이 반환된다.
	 */
	@SuppressWarnings("unchecked")
	public List<StreamEvent> listStreamEvents(String streamEventName)
	{
		Session session = this._sessionFactory.openSession();
		
		try
		{
			Criteria criteria = session.createCriteria(StreamEvent.class)
					.add(Restrictions.like("eventName", streamEventName));
			
			List<StreamEvent> streamEvents = (List<StreamEvent>)criteria.list();
			
			return streamEvents;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
	/**
	 * 스트림 이벤트 정보를 저장한다.
	 * @param streamEvent 저장하려는 스트림 이벤트 정보를 설정한다.
	 * @return 스트림 이벤트 정보가 저장되면 true, 그렇지 않으면 false가 반환된다.
	 */
	public boolean saveStreamEvent(StreamEvent streamEvent)
	{
		Session session = this._sessionFactory.openSession();
		
		Transaction transaction = session.beginTransaction();
		
		try
		{
			/*if (streamEvent.getEventId() != null && streamEvent.getEventId() > 0)
			{
				Criteria criteria = session.createCriteria(StreamEvent.class)
						.add(Restrictions.eq("eventId", streamEvent.getEventId()));
				
				String eventName = streamEvent.getEventName();
				String description = streamEvent.getDescription();
				
				streamEvent = (StreamEvent)criteria.uniqueResult();
			}*/
			
			session.saveOrUpdate(streamEvent);
			
			return true;
		}
		catch (Exception error)
		{
			transaction.rollback();
			
			throw error;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
	/**
	 * 스트림 시냅스 목록을 조회한다.
	 * @param eventId 조회하려는 스트림 시냅스에 대한 스트림 이벤트 아이디를 설정한다.
	 * @param sourceEndPointId 조회하려는 스트림 시냅스의 출발 끝점 아이디를 설정한다.
	 * @param destinationEndPointId 조회하려는 스트림 시냅스의 도착 끝점 아이디를 설정한다.
	 * @return 조회된 스트림 시냅스 목록이 반환된다.
	 */
	@SuppressWarnings("unchecked")
	public List<StreamSynapse> listStreamSynapses(long eventId, long sourceEndPointId, long destinationEndPointId)
	{
		Session session = this._sessionFactory.openSession();
		
		try
		{
			Criteria criteria = session.createCriteria(StreamSynapse.class)
					.add(Restrictions.eq("streamEvent.eventId", eventId));
			
			if (sourceEndPointId > 0)
			{
				criteria.add(Restrictions.eq("sourceEndPointId", sourceEndPointId));
			}
			
			if (destinationEndPointId > 0)
			{
				criteria.add(Restrictions.eq("destinationEndPointId", destinationEndPointId));
			}
			
			List<StreamSynapse> streamSynapses = (List<StreamSynapse>)criteria.list();
			
			return streamSynapses;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
	/**
	 * 스트림 시냅스 정보를 저장한다.
	 * @param eventId 스트림 시냅스에 대한 스트림 이벤트 아이디를 설정한다.
	 * @param streamSynapse 저장하려는 스트림 시냅스 정보를 설정한다.
	 * @return 스트림 시냅스 정보가 저장되면 true, 그렇지 않으면 false가 반환된다.
	 */
	public boolean saveStreamSynapse(long eventId, StreamSynapse streamSynapse)
	{
		Session session = this._sessionFactory.openSession();
		
		Transaction transaction = session.beginTransaction();
		
		try
		{
			// 스트림 이벤트 아이디가 반드시 필요하다.
			if (eventId < 1)
			{
				return false;
			}
			// 스트림 이벤트 아이디에 대한 스트림 이벤트 정보를 조회하여 스트림 시냅스 정보에 설정해준다.
			else
			{
				Criteria criteria = session.createCriteria(StreamEvent.class)
						.add(Restrictions.eq("eventId", eventId));
				
				StreamEvent streamEvent = (StreamEvent)criteria.uniqueResult();
				
				streamSynapse.setStreamEvent(streamEvent);
			}
			
			session.saveOrUpdate(streamSynapse);
			
			return true;
		}
		catch (Exception error)
		{
			transaction.rollback();
			
			throw error;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
	/**
	 * 스트림 시냅스의 전달 매체 목록을 조회한다.
	 * @param synapseId 조회하려는 전달 매체에 대한 스트림 시냅스 아이디를 설정한다.
	 * @return 조회된 스트림 시냅스의 전달 매체 목록이 반환된다.
	 */
	@SuppressWarnings("unchecked")
	public List<StreamSynapseTransmitter> listStreamSynapseTransmitters(long synapseId)
	{
		Session session = this._sessionFactory.openSession();
		
		try
		{
			Criteria criteria = session.createCriteria(StreamSynapseTransmitter.class)
					.add(Restrictions.eq("streamSynapse.synapseId", synapseId));
			
			List<StreamSynapseTransmitter> streamSynapseTransmitters = (List<StreamSynapseTransmitter>)criteria.list();
			
			return streamSynapseTransmitters;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
	/**
	 * 스트림 시냅스 전달 매체 정보를 저장한다.
	 * @param synapseId 저장하려는 전달 매체에 대한 스트림 시냅스 아이디를 설정한다.
	 * @param streamSynapseTransmitter 저장하려는 스트림 시냅스 전달 매체를 설정한다.
	 * @return 스트림 시냅스 전달 매체 정보가 저장되었으면 true, 그렇지 않으면 false가 반환된다.
	 */
	public boolean saveStreamSynapseTransmitter(long synapseId, StreamSynapseTransmitter streamSynapseTransmitter)
	{
		Session session = this._sessionFactory.openSession();
		
		Transaction transaction = session.beginTransaction();
		
		try
		{
			// 스트림 시냅스 아이디가 반드시 필요하다.
			if (synapseId < 1)
			{
				return false;
			}
			// 스트림 시냅스 아이디에 대한 스트림 시냅스 정보를 조회하여 전달 매체 정보에 설정해준다.
			else
			{
				Criteria criteria = session.createCriteria(StreamSynapse.class)
						.add(Restrictions.eq("synapseId", synapseId));
				
				StreamSynapse streamSynapse = (StreamSynapse)criteria.uniqueResult();
				
				streamSynapseTransmitter.setStreamSynapse(streamSynapse);
			}
			
			session.saveOrUpdate(streamSynapseTransmitter);
			
			return true;
		}
		catch (Exception error)
		{
			transaction.rollback();
			
			throw error;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
	/**
	 * 스트림 시냅스 계수 목록을 조회한다.
	 * @param synapseId 조회하려는 계수에 대한 스트림 시냅스 아이디를 설정한다.
	 * @return 조회된 스트림 시냅스 계수 목록이 반환된다.
	 */
	@SuppressWarnings("unchecked")
	public List<StreamSynapseCoefficient> listStreamSynapseCoefficients(long synapseId)
	{
		Session session = this._sessionFactory.openSession();
		
		try
		{
			Criteria criteria = session.createCriteria(StreamSynapseCoefficient.class)
					.add(Restrictions.eq("id.synapseId", synapseId));
			
			List<StreamSynapseCoefficient> streamSynapseCoefficients = (List<StreamSynapseCoefficient>)criteria.list();
			
			return streamSynapseCoefficients;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
	
	/**
	 * 스트림 시냅스의 계수 정보를 저장한다.
	 * @param synapseId 저장하려는 계수에 대한 스트림 시냅스 아이디를 설정한다.
	 * @param streamSynapseCoefficient 저장하려는 스트림 시냅스 계수 정보를 설정한다.
	 * @return 스트림 시냅스 계수 정보가 저장되면 true, 그렇지 않으면 false가 반환된다.
	 */
	public boolean saveStreamSynapseCoefficient(long synapseId, StreamSynapseCoefficient streamSynapseCoefficient)
	{
		Session session = this._sessionFactory.openSession();
		
		Transaction transaction = session.beginTransaction();
		
		try
		{
			// 스트림 시냅스 아이디가 반드시 필요하다.
			if (synapseId < 1)
			{
				return false;
			}
			// 스트림 시냅스 아이디에 대한 스트림 시냅스 정보를 조회하여 전달 매체 정보에 설정해준다.
			else
			{
				Criteria criteria = session.createCriteria(StreamSynapse.class)
						.add(Restrictions.eq("synapseId", synapseId));
				
				StreamSynapse streamSynapse = (StreamSynapse)criteria.uniqueResult();
				
				streamSynapseCoefficient.setStreamSynapse(streamSynapse);
			}
			
			session.saveOrUpdate(streamSynapseCoefficient);
			
			return true;
		}
		catch (Exception error)
		{
			transaction.rollback();
			
			throw error;
		}
		finally
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
	}
}